"""
/*
 * Copyright 2011 OpenWAF.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
 """
import sys

from JavaLangAST import Literal
import os

def readLiteral(ts):#wrong
	ci = ts.getCurrentIndex()
	tok = ts.getCurrentToken()
	if tok.data[0] == "\"":
		lit = Literal(Literal.STRING, tok)
		ts.getNextToken()
		return lit
	elif tok.data[0] == "\'":
		lit = Literal(Literal.CHAR, tok)
		ts.getNextToken()
		return lit
	elif tok.data == "true":
		lit = Literal(Literal.TRUE, None)
		ts.getNextToken()
		return lit
	elif tok.data == "false":
		lit = Literal(Literal.FALSE, None)
		ts.getNextToken()
		return lit
	elif tok.data == "null":
		lit = Literal(Literal.NULL, None)
		ts.getNextToken()
		return lit
	return readOtherLiteral(ts)
	#if lit!=None:
	#		print "Found Lit",lit.value
	#		return lit
	#return None
def readOtherLiteral(ts):
	ci = ts.getCurrentIndex()
	lit = readIntLiteral(ts)
	if lit != None:return lit
	ts.setCurrentIndex(ci)

	lit = readLongLiteral(ts)
	if lit != None:return lit
	ts.setCurrentIndex(ci)

	lit = readNormalFloatOrDouble(ts)
	if lit != None:return lit
	ts.setCurrentIndex(ci)

	lit = readExponentFloatOrDouble(ts)
	if lit != None:return lit
	ts.setCurrentIndex(ci)

	lit = readDotFloatOrDoubleLiteral(ts)
	if lit != None:return lit
	ts.setCurrentIndex(ci)
	return None
def readIntLiteral(ts):
	data = ""
	tok = ts.getCurrentToken()
	if len(tok.data) > 2 and (tok.data[0:2] in ["0x", "0X"]):
		if isHexString(tok.data[2:]):
			ts.getNextToken()
			return Literal(Literal.INT, tok.data)
	else:
		if not tok.data.isdigit(): return None
		data = tok.data
		ntok = ts.getNextToken()
		if ntok.data[0] == ".":return None
		return Literal(Literal.INT, tok.data)

def readLongLiteral(ts):
	tok = ts.getCurrentToken()
	if not (tok.data[-1:] in ["l", "L"]):return None
	if tok.data[0:-1].isdigit():
		ts.getNextToken()#acccepted
		return Literal(Literal.LONG, tok.data)
	elif  tok.data[0:2]in ["0x", "0X"]:
		if isHexString(tok.data[2:-1]):
			ts.getNextToken()
			return Literal(Literal.LONG, tok.data)
	return None
def readNormalFloatOrDouble(ts):
	tok = ts.getCurrentToken()
	if tok.data[-1:] in ["f", "d", "F", "D"] and tok.data[:-1].isdigit():
		ts.getNextToken()
		if tok.data[-1:] in ["f", "F"]:
			return Literal(Literal.FLOAT, tok.data)
		else:
			return Literal(Literal.DOUBLE, tok.data)
	return None
def readExponentFloatOrDouble(ts):
	ci = ts.getCurrentIndex()
	tok = ts.getCurrentToken()
	if not "e" in tok.data.lower():return None
	if tok.data[-1:] in ["e", "E"]:
		data = tok.data
		tok = ts.getNextToken()
		if tok.data in ["+", "-"]:
			tok = ts.getNextToken()
			if tok.data.isdigit():
				data += tok.data
				ts.getNextToken()
				return Literal(Literal.DOUBLE, data)
			elif tok.data[:-1].isdigit() and tok.data[-1:] in ["f", "d", "F", "D"]:
				data += tok.data
				ts.getNextToken()
				if tok.data[-1:] in ["f", "F"]:
					return Literal(Literal.FLOAT, data)
				else:
					return Literal(Literal.DOUBLE, data)

	elif tok.data[-1:] in ["f", "d", "F", "D"]:
		index = tok.data.lower().find("e")
		if tok.data[:index].isdigit() and tok.data[index + 1:-1].isdigit():
			ts.getNextToken()
			if tok.data[-1:] in ["f", "F"]:
				return Literal(Literal.FLOAT, tok.data)
			else:
				return Literal(Literal.DOUBLE, tok.data)
	else:
		index = tok.data.lower().find('e')
		if tok.data[:index].isdigit() and tok.data[index + 1:].isdigit():
			ts.getNextToken()
			return Literal(Literal.DOUBLE, tok.data)
	ts.setCurrentIndex(ci)
	return None





def readDotFloatOrDoubleLiteral(ts):
	ci = ts.getCurrentIndex()
	tok = ts.getCurrentToken()
	if tok.data == ".":
		ts.getNextToken()
		ret = readAfterDotFloatOrDoubleLiteral(ts)
		if ret == None:
			ts.setCurrentIndex(ci)
			return None
		ret.value = "." + ret.value
		return ret
	elif  tok.data.isdigit():
		data = tok.data
		tok = ts.getNextToken()
		if tok.data == ".":
			data = data + "."
			tok = ts.getNextToken()
		if tok.data in ["f", "d", "F", "D"]:
			data = data + tok.data
			ts.getNextToken()
			if tok.data in ["f", "D"]:
				return Literal(Literal.FLOAT, data)
			else:
				return Literal(Literal.DOUBLE, data)
		#TODO:code will never reach this
		ret = readAfterDotFloatOrDoubleLiteral(ts)
		if ret == None:
			#('0' .. '9')+ '.' ('0' .. '9')* Exponent?
			#literal "10." is also valid here
			ts.setCurrentIndex(ci)
			ts.getNextToken()
			ts.getNextToken()
			return Literal(Literal.FLOAT, data)
		ret.value = data + ret.value
		return ret





def readAfterDotFloatOrDoubleLiteral(ts):
	data = ""
	tok = ts.getCurrentToken()
	if not (tok.data[0].isdigit() or tok.data[0] in ["e", "E"]):return None#optimization
	if tok.data.isdigit():
		data += tok.data
		ts.getNextToken()#accept two tokens
		return Literal(Literal.DOUBLE, data)#.4
	elif tok.data[:-1].isdigit() and tok.data[-1:] in ["f", "F"]:
		data += tok.data
		ts.getNextToken()#accept two tokens
		return Literal(Literal.FLOAT, data) #.34f
	elif tok.data[:-1].isdigit() and tok.data[-1:] in ["d", "D"]:
		data += tok.data
		ts.getNextToken()#accept two tokens
		return Literal(Literal.DOUBLE, data)#.45D
	elif tok.data[:-1].isdigit() and tok.data[-1:] in ["e", "E"]:
		data += tok.data
		tok = ts.getNextToken()
		if not (tok.data in ["+", "-"]):return None
		data += tok.data
		tok = ts.getNextToken()
		if tok.data.isdigit():
			ts.getNextToken()
			data += tok.data
			return Literal(Literal.DOUBLE, data)#.4e+4,.54545e-6
		else:
			if not tok.data[-1:] in ["f", "d", "F", "D"]:return None
			if not tok.data[:-1].isdigit():return None
			ts.getNextToken()
			data += tok.data
			if tok.data[-1:] in ["f", "F"]:
				return Literal(Literal.FLOAT, data)
			else:
				return Literal(Literal.DOUBLE, data)
	elif "e" in tok.data.lower():
		index = tok.data.lower().find("e")
		if tok.data[:index].isdigit():
			if tok.data[index + 1:].isdigit():
				ts.getNextToken()
				data = data + tok.data
				return Literal(Literal.DOUBLE, data)
			elif tok.data[index + 1:-1].isdigit() and tok.data[-1:] in ["f", "d", "F", "D"]:
				ts.getNextToken()
				data += tok.data
				if tok.data[-1:] in ["f", "F"]:
					return Literal(Literal.FLOAT, data)
				else:
					return Literal(Literal.DOUBLE, data)
		elif tok.data[0] in ["e", "E"]:
			if tok.data[1:].isdigit():
				ts.getNextToken()
				return Literal(Literal.DOUBLE, tok.data)
			elif tok.data[-1:] in ["f", "d", "F", "D"]:
				ts.getNextToken()
				if tok.data[-1:] in ["f", "F"]:
					return Literal(Literal.FLOAT, tok.data)
				else:
					return Literal(Literal.DOUBLE, tok.data)
			elif tok.data in ["e", "E"]:
				myi = ts.getCurrentIndex()
				data = tok.data
				tok = ts.getNextToken()
				if tok.data in ["+", "-"]:
					data += tok.data
					tok = ts.getNextToken()
					if tok.data.isdigit():
						ts.getNextToken()
						data += tok.data
						return Literal(Literal.DOUBLE, data)
					elif tok.data[-1:] in ["f", "d", "F", "D"]:
						ts.getNextToken()
						data += tok.data
						if tok.data[-1:] in ["f", "F"]:
							return Literal(Literal.FLOAT, data)
						else:
							return Literal(Literal.FLOAT, data)


	return None


def isHexString(s):
	for i in range(0, len(s)):
		if not isHex(s[i]):return False
	return True

def isHex(ch):
	return ch  in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F']
